﻿//-----------------------------------------------------------------------
// <copyright>
// This file is subject to the terms and conditions of the Microsoft Public License (MS-PL).
// See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL for more details.
// </copyright>
//----------------------------------------------------------------------- 
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Xml;

namespace Fulcrum.ControlGenerator
{
    /// <summary>
    /// Holds global configuration data.  Self-populate from an XML file.
    /// </summary>
    class ControlGeneratorXmlConfiguration : Fulcrum.ControlGenerator.IControlGeneratorConfiguration
    {
        Dictionary<string, IControlConfiguration> controlConfigurations;

        public ControlGeneratorXmlConfiguration(string configurationFile)
        {
            this.controlConfigurations = new Dictionary<string, IControlConfiguration>(StringComparer.InvariantCultureIgnoreCase);

            LoadConfigurationFile(configurationFile);
        }

        public string RoutedPropertyEventArgsFactory
        {
            get;
            private set;
        }

        public string TemplatePartFactory
        {
            get;
            private set;
        }

        public string OptionalTemplatePartFactory
        {
            get;
            private set;
        }

        public string Company
        {
            get;
            private set;
        }

        public string Copyright
        {
            get;
            private set;
        }

        public string Namespace
        {
            get;
            private set;
        }

        public ICollection<IControlConfiguration> ControlConfigurations
        {
            get
            {
                return this.controlConfigurations.Values;
            }
        }

        public IControlConfiguration GetControlConfiguration(string name)
        {
            return this.controlConfigurations[name];
        }

        void LoadConfigurationFile( string file )
        {
            var fileStream = GetXmlStream(file);

            using (fileStream)
            {
                XmlReaderSettings readerSettings = new XmlReaderSettings();
                readerSettings.IgnoreWhitespace = true;
                readerSettings.IgnoreComments = true;

                XmlReader fileReader = XmlReader.Create(fileStream, readerSettings);

                using (fileReader)
                {
                    fileReader.MoveToContent();
                    ParseXmlSource(fileReader);
                }
            }
        }

        protected virtual Stream GetXmlStream(string file)
        {
            FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read);
            return fileStream;
        }

        private void ParseXmlSource( XmlReader xmlReader )
        {
            Debug.Assert(xmlReader.IsStartElement() && 0 == String.Compare("ControlGenerator", xmlReader.Name, StringComparison.Ordinal));

            ParseGlobalSettings(xmlReader);

            while (xmlReader.IsStartElement() && xmlReader.Name == "Control")
            {
                switch (xmlReader.Name)
                {
                    case "Control":
                        var controlConfig = CreateControlConfiguration(xmlReader);
                        this.controlConfigurations.Add(controlConfig.Name, controlConfig);
                        break;
                    default:
                        Debug.Fail("Invalid name");
                        break;
                }
            }
        }

        protected virtual IControlConfiguration CreateControlConfiguration(XmlReader xmlReader)
        {
            var controlConfig = new ControlXmlConfiguration(xmlReader);
            return controlConfig;
        }

        private void ParseGlobalSettings(XmlReader xmlReader)
        {
            this.RoutedPropertyEventArgsFactory = xmlReader["RoutedPropertyEventArgsFactory"];
            this.TemplatePartFactory = xmlReader["TemplatePartFactory"];
            this.OptionalTemplatePartFactory = xmlReader["OptionalTemplatePartFactory"];
            this.Company = xmlReader["Company"];
            this.Copyright = xmlReader["Copyright"];
            this.Namespace = xmlReader["Namespace"];

            xmlReader.Read();
        }
    }
}
